package com.xuecheng.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.auth.mapper.XcUserMapper;
import com.xuecheng.auth.mapper.XcUserRoleMapper;
import com.xuecheng.auth.model.dto.AuthParamsDto;
import com.xuecheng.auth.model.dto.XcUserExt;
import com.xuecheng.auth.model.po.XcUser;
import com.xuecheng.auth.model.po.XcUserRole;
import com.xuecheng.auth.service.AuthService;
import com.xuecheng.auth.service.WxAuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * 微信扫码认证
 */
@Slf4j
@Service("wx_authservice")
public class WxAuthServiceImpl implements WxAuthService,AuthService {
    @Autowired
    XcUserMapper xcUserMapper;

    @Autowired
    RestTemplate restTemplate;

    @Value("${weixin.appid}")
    String appid;

    @Value("${weixin.secret}")
    String secret;

    @Autowired
    WxAuthService currentProxy;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    XcUserRoleMapper xcUserRoleMapper;

    @Override
    public XcUserExt execute(AuthParamsDto authParamsDto) {
        //账号
        String username = authParamsDto.getUsername();
        XcUser user = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>().eq(XcUser::getUsername, username));
        if(user==null){
            //返回空表示用户不存在
            throw new RuntimeException("账号不存在");
        }
        XcUserExt xcUserExt = new XcUserExt();
        BeanUtils.copyProperties(user,xcUserExt);
        return xcUserExt;
    }

    /**
     * 微信认证
     * @param code
     * @return
     */
    @Override
    public XcUser wxAuth(String code) {
        //收到code调用微信接口申请access_token
        Map<String,String> access_token_map = getAccess_token(code);
        if(access_token_map == null)    return null;
        System.out.println(access_token_map);
        String openid = access_token_map.get("openid");
        String access_token = access_token_map.get("access_token");
        //拿access_token到微信查询用户信息
        Map<String,String> userInfo = getUserInfo(access_token,openid);
        if(userInfo == null){
            return null;
        }
        //添加用户到数据库
        return currentProxy.addWxUser(userInfo);
    }

    /**
     * 申请访问令牌,响应示例
     * {
     *  "access_token":"ACCESS_TOKEN",
     *  "expires_in":7200,
     *  "refresh_token":"REFRESH_TOKEN",
     *  "openid":"OPENID",
     *  "scope":"SCOPE",
     *  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
     * }
     */
    private Map<String,String> getAccess_token(String code){
        //要请求这个地址获取令牌
        String wxUrl_template = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
        //请求微信地址
        String wxUrl = String.format(wxUrl_template,appid,secret,code);
        log.info("调用微信接口申请access_token, url:{}",wxUrl);
        ResponseEntity<String> exchange = restTemplate.exchange(wxUrl, HttpMethod.POST,null,String.class);
        String result = exchange.getBody();
        log.info("调用微信接口申请access_token, 返回值:{}",result);
        return JSON.parseObject(result,Map.class);
    }

    /**获取用户信息，示例如下：
     * {
     *  "openid":"OPENID",
     *  "nickname":"NICKNAME",
     *  "sex":1,
     *  "province":"PROVINCE",
     *  "city":"CITY",
     *  "country":"COUNTRY",
     *  "headimgurl": "https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
     *  "privilege":[
     *      "PRIVILEGE1",
     *      "PRIVILEGE2"
     *  ],
     *  "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
     * }
     */
    private Map<String, String> getUserInfo(String accessToken, String openid) {
        //请求这个地址获取用户信息
        String wxUrl_template = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";
        //请求微信地址
        String wxUrl = String.format(wxUrl_template,accessToken,openid);
        log.info("调用微信接口申请access_token, url:{}", wxUrl);
        ResponseEntity<String> exchange = restTemplate.exchange(wxUrl,HttpMethod.POST,null,String.class);
        //防止乱码，进行转码
        String result = new String(exchange.getBody().getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);
        log.info("调用微信接口申请access_token: 返回值:{}", result);
        return JSON.parseObject(result, Map.class);
    }

    /**
     * 保存用户信息到数据库
     * @param userInfoMap
     * @return
     */
    @Transactional
    @Override
    public XcUser addWxUser(Map<String, String> userInfoMap) {
        String unionid = userInfoMap.get("unionid");
        //根据unionid查询用户信息
        XcUser user = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>()
                .eq(XcUser::getWxUnionid,unionid));
        if(user != null){
            return user;
        }
        user = new XcUser();
        user.setWxUnionid(unionid);
        //设置从微信中获取的信息
        user.setNickname(userInfoMap.get("nickname"));
        user.setUserpic(userInfoMap.get("headimgurl"));
        user.setName(userInfoMap.get("nickname"));
        user.setUsername(unionid);
        user.setPassword(passwordEncoder.encode(unionid));
        user.setUtype("101001");//学生类型
        user.setStatus("1");//用户状态
        user.setCreateTime(LocalDateTime.now());
        xcUserMapper.insert(user);
        XcUserRole userRole = new XcUserRole();
        userRole.setUserId(user.getId());
        userRole.setRoleId(17L);    //学生角色id
        userRole.setCreateTime(LocalDateTime.now());
        xcUserRoleMapper.insert(userRole);
        return user;
    }
}
